package analyzer;

import java.util.LinkedList;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import map.MapGraphAnalyzer;
import map.MapGraphDatabase;
import map.graph.MapGraph;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

import com.taxi.server.carsearch.graph.Way;
import com.taxi.server.carsearch.mathutils.Line;
import com.taxi.server.carsearch.mathutils.PointD;

public class JMSDataReciever implements MessageListener {

	private ActiveMQConnectionFactory connectionFactory;
	private Connection connection;
	private Session session;
	private Destination destination1;
	private Destination destination2;

	private String subjectData = "ANALYZE";
	private String subjectCoords = "COORDS";

	private MapGraph graph = MapGraphDatabase.getInstance().loadMapGraph();

	public JMSDataReciever() {
		String url = ActiveMQConnection.DEFAULT_BROKER_URL;
		// Name of the queue we will be sending messages to
		try {
			// Getting JMS connection from the server and starting it
			connectionFactory = new ActiveMQConnectionFactory(url);
			connection = connectionFactory.createConnection();
			connection.start();

			// JMS messages are sent and received using a Session. We will
			// create here a non-transactional session object. If you want
			// to use transactions you should set the first parameter to 'true'
			session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

			// Destination represents here our queue 'TESTQUEUE' on the
			// JMS server. You don't have to do anything special on the
			// server to create it, it will be created automatically.
			destination1 = session.createQueue(subjectData);
			destination2 = session.createQueue(subjectCoords);

		} catch (Exception e) {
			System.out.println(e);
		}
	}

	@Override
	public void onMessage(Message msg) {
		long t1 = System.currentTimeMillis();
		TextMessage textMessage = (TextMessage) msg;
		try {
			if (msg.getJMSDestination().toString().endsWith(subjectData)) {
				LinkedList<PointD> points = new LinkedList<PointD>();
				LinkedList<Integer> times = new LinkedList<Integer>();
				double minlat = 100;
				double minlon = 100;
				double maxlat = -1;
				double maxlon = -1;

				String mes = textMessage.getText();
				System.out.println(mes);
				String[] samples = mes.split("\\|");

				for (String s : samples) {
					String[] vals = s.split(" ");
					double lon = Double.valueOf(vals[0]);
					double lat = Double.valueOf(vals[1]);
					if (lat < minlat) {
						minlat = lat;
					}
					if (lat > maxlat) {
						maxlat = lat;
					}
					if (lon < minlon) {
						minlon = lon;
					}
					if (lon > maxlon) {
						maxlon = lon;
					}
					points.add(new PointD(lon, lat));
					times.add(Integer.valueOf(vals[2]));
				}

				MapGraph mg = graph.subGraph(minlat, minlon, maxlat, maxlon);

				PointD prev = points.pop();
				LinkedList<Way> ways = new LinkedList<Way>();
				// MapGraphDrawer drawer = new MapGraphDrawer(mg);
				int k = 0;
				for (PointD cur : points) {
					Line line = new Line(prev, cur);
					prev = cur;
					Way way = MapGraphAnalyzer.getClosestWay(line, mg);
					if (way == null) {
						times.remove(k);
						continue;
					}
					ways.add(way);
					// drawer.addWay(way);
					// drawer.addLine(line);
					MapGraphDatabase.getInstance().addOperativeData(way,
							times.get(k));
					++k;
				}

				// System.out.println(ways.toString());
				// drawer.setVisible(true);
			} else if (msg.getJMSDestination().toString()
					.endsWith(subjectCoords)) {
				String mes = textMessage.getText();
				System.out.println("Coords got:" + mes);
				String[] s = mes.split("\\|");
				double lon = Double.valueOf(s[0]);
				double lat = Double.valueOf(s[1]);
				String login = s[2];
				MapGraphDatabase.getInstance().updateDriverPosition(lon, lat,
						login);
			}
		} catch (JMSException e) {
			e.printStackTrace();
		}

		long t2 = System.currentTimeMillis();
		System.out.println("Time: " + (t2 - t1));

	}

	public void close() throws JMSException {
		connection.close();
	}

	/**
	 * starts consuming messages using JMS
	 */
	public void start() throws JMSException {
		session.createConsumer(destination1).setMessageListener(this);
		session.createConsumer(destination2).setMessageListener(this);
	}

	public static void main(String[] args) {
		JMSDataReciever rec = new JMSDataReciever();
		try {
			rec.start();
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
}
